/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pa165.machineryrental.dao.impl;

import cz.muni.fi.pa165.machineryrental.dao.RentalDAO;
import cz.muni.fi.pa165.machineryrental.entities.Customer;
import cz.muni.fi.pa165.machineryrental.entities.Machine;
import cz.muni.fi.pa165.machineryrental.entities.Rental;
import java.util.Date;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;

/**
 * Implementation of RentalDAO which is used on persisting and other operations
 * on rentals in database.
 *
 * @author Marian Lorenc, 374122
 */
public class RentalDAOImpl implements RentalDAO {

    /**
     * Entity Manager for operations.
     */
    private EntityManager em;

    /**
     * Creates new instance of RentalDAOImpl on performing operations on
     * entities into or from database.
     *
     * @param em Entity manager running the operations to database.
     */
    public RentalDAOImpl(EntityManager em) {
        if (em == null) {
            throw new IllegalArgumentException("Given Entity manager cannot be null.");
        }

        this.em = em;
    }

    /**
     * @see cz.muni.fi.pa165.machineryrental.dao.RentalDAO#getById(long)
     */
    @Override
    public Rental getById(long id) {
        if (id < 0) {
            throw new IllegalArgumentException("ID cannot be negative");
        }

        return em.find(Rental.class, id);
    }

    /**
     * @see
     * cz.muni.fi.pa165.machineryrental.dao.RentalDAO#create(cz.muni.fi.pa165.machineryrental.entities.Rental)
     */
    @Override
    public void create(Rental rental) {
        if (rental == null) {
            throw new IllegalArgumentException("Rental cannot be null");
        }

        this.em.persist(rental);
    }

    /**
     * @see
     * cz.muni.fi.pa165.machineryrental.dao.RentalDAO#update(cz.muni.fi.pa165.machineryrental.entities.Rental)
     */
    @Override
    public void update(Rental rental) {
        if (rental == null) {
            throw new IllegalArgumentException("Rental cannot be null");
        }

        this.em.merge(rental);
    }

    /**
     * @see
     * cz.muni.fi.pa165.machineryrental.dao.RentalDAO#remove(cz.muni.fi.pa165.machineryrental.entities.Rental)
     */
    @Override
    public void remove(Rental rental) {
        if (rental == null) {
            throw new IllegalArgumentException("Rental cannot be null");
        }

        this.em.remove(rental);
    }

    /**
     * @see cz.muni.fi.pa165.machineryrental.dao.RentalDAO#findAll()
     */
    @Override
    public List<Rental> findAll() {
        TypedQuery<Rental> query = this.em.createQuery("FROM Rental R", Rental.class);
        return query.getResultList();
    }

    /**
     * @see
     * cz.muni.fi.pa165.machineryrental.dao.RentalDAO#findByCustomer(cz.muni.fi.pa165.machineryrental.entities.Customer)
     */
    @Override
    public List<Rental> findByCustomer(Customer customer) {
        if (customer == null) {
            throw new IllegalArgumentException("Customer cannot be null");
        }

        TypedQuery<Rental> query = this.em.createQuery("SELECT r FROM Rental r WHERE r.customer = :customer",
                Rental.class);
        query = query.setParameter("customer", customer);
        return query.getResultList();
    }

    /**
     * @see
     * cz.muni.fi.pa165.machineryrental.dao.RentalDAO#findByMachine(cz.muni.fi.pa165.machineryrental.entities.Machine)
     */
    @Override
    public List<Rental> findByMachine(Machine machine) {

        if (machine == null) {
            throw new IllegalArgumentException("Machine cannot be null");
        }

        TypedQuery<Rental> query = this.em.createQuery("SELECT r FROM Rental r WHERE r.machine = :machine",
                Rental.class).setParameter("machine", machine);

        return query.getResultList();
    }

    /**
     * @see
     * cz.muni.fi.pa165.machineryrental.dao.RentalDAO#findByIntervalOfRent(java.util.Date,
     * java.util.Date)
     */
    @Override
    public List<Rental> findByIntervalOfRent(Date startDate, Date endDate) {

        if (startDate == null) {
            throw new IllegalStateException("StartDate cannot be null");
        }

        if (endDate == null) {
            throw new IllegalStateException("EndDate cannot be null");
        }

        TypedQuery<Rental> query = this.em.createQuery(
                "SELECT r FROM Rental r WHERE r.dateOfRent >= :startDate AND r.dateOfRent <= :endDate",
                Rental.class).setParameter("startDate", startDate).setParameter("endDate", endDate);

        return query.getResultList();
    }
}
